#!/usr/bin/python
# Tkinter GUI for pyDSL2HTM converter
#

import os
import sys
from Tkinter import *
import tkMessageBox
import tkSimpleDialog
import tkFileDialog
import tkColorChooser

import threading

root = Tk()
root.title('DSL2HTML Converter')
root.resizable(0,0)

globalStatus = 'Idle'
globalStop = False
job = None


myFormats = [
    ('Lingvo DSL source','*.dsl'),
    ('HTML markup','*.htm,*.html'),
    ('Plain text','*.txt'),
    ('All Files','*.*'),
    ]

def destroyApp():
    if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
        root.destroy()

def logMessage(msg):
    if sys.stdout:
        print msg
    updateStatusHook(msg)


def quitApp(event):
    destroyApp()

def newFile():
    if tkMessageBox.askyesno("New", "Create new file?"):
        pass


def helpAbout():
    if tkMessageBox.showinfo("DSL2SQLite",

    "DSL2HTML Converter\n\n"+
    "Convert Lingvo DSL source files to HTML format\n"+
    "For details, see http://pydictionary.googlecode.com\n"+
    "copywhite, xhuman(c) 2009"):
        pass

#def openFile():
    #f = tkFileDialog.askopenfile(parent=root,mode='rb',filetypes=myFormats,title='Please select a file')
    #if f != None:
        #data = f.read()
        #f.close()
        #print "I got %d bytes from the file." % len(data)

def openFileName(event=None):
    fname = tkFileDialog.askopenfilename(parent=root,filetypes=myFormats,title='Please select source file')
    logMessage('Source file: ' + fname)
#    global srcName
#    global destName

    if fname:
        srcName.set(fname)
    if not destName.get() and len(fname) > 3:
        destName.set(fname[:-3]+'html')

    #barename = os.path.splitext(os.path.basename(fname))[0]
    #if barename:
        #table.set(barename)
    return "break"

def openDestFileName(event=None):
#    global destName
    fname = tkFileDialog.askopenfilename(parent=root,filetypes=[('All Files','*.*')],title='Please select target file')
    if fname:
        destName.set(fname)
        logMessage('Target file: ' + fname)
    else:
        logMessage('No target file selected ')

#def setTitle():
    #table_name = tkSimpleDialog.askstring('Set SQLite table name', 'table name')
    #logMessage('Selected table:' + str(table_name))
    #table.set(table_name)

def updateStatusHook(data=None, show_hint=True, show_log=True, overwritePreviousLine=False):
    global globalStatus
    #print 'data', data, 'dbg overwrite:', overwritePreviousLine
    if show_hint:
        statusVar.set(str(data))

    if show_log:
        globalStatus = str(data)
        #if overwritePreviousLine:
        #    log.delete("end -1 lines" , "end")
        log.insert(END, str('\n' + data))
        #log.insert(END, '\n')
        log.see('end')

    if globalStop:
        return True
    else:
        return False

def statusHint(hint):
#    global globalStatus
#    globalStatus = statusVar.get()
    updateStatusHook(hint, show_hint=True, show_log=False)

def statusRevert():
#    global globalStatus
    if globalStatus:
        statusVar.set(globalStatus)

#def saveFile():
    #filename = tkFileDialog.asksaveasfilename(parent=root,filetypes=myFormats,title="Save image as...")
    #if len(filename) > 0:
        #print "Now saving as %s" % (filename)


def setColor():
#    global log
    col= tkColorChooser.askcolor()
    # workaround: on linux col[1] returns object, not string
    col2 = isinstance(col[1], str) and col[1] or col[1].string
    log.config(background=col2)
    statusHint('Color set to: ' + col2)

class ConverterThread(threading.Thread):
    def __init__(self, srcName=None, destName=None, pretty_html=True, callbackFunc=None):
        threading.Thread.__init__(self, name='converterThread')
        self.infile = srcName
        self.outfile = destName
        self.prettyHtml = pretty_html
        self.callbackFunc = callbackFunc
        self.running = True
#        self._stopevent = threading.Event()
#        self._sleepperiod = 1.0
    def run(self):
        try:
            import pyDSL2HTM2
        except:
            updateStatusHook('ERROR: pyDSL2HTM.py not found! Conversion aborted...')
            sys.exit(-1)
        try:
            pyDSL2HTM2.convert_dsl(input_file=self.infile,
                                   output_file=self.outfile,
                                   in_enc=None,
                                   out_enc=None,
                                   pretty_html=self.prettyHtml,
                                   callback_func=self.callbackFunc)
        except Exception, e:
            updateStatusHook(str(e))

#        count = 0
#        while self.running:
#            count += 1
#            print "loop %d" % (count,)
#            self._stopevent.wait(self._sleepperiod)

        print 'Finished background job'
#    def join(self, timeout=None):
#        self._stopevent.set()
#        threading.Thread.join(self, timeout)

def srcReturnHadler(event=None):
    if not srcName.get() or srcName.get().startswith('Click'):
        openFileName()
    else:
        doConversion()

def doConversion(event=None):
    global globalStatus
    global job
    if job:
        updateStatusHook("Conversion already in progress")
        return

    if not srcName.get() or srcName.get().startswith('Click'):
        globalStatus = 'No source file selected. Please select a source file first!'
        logMessage(globalStatus)
        return
    if not destName.get():
        logMessage('No target file selected! Please select select target file.')
        return
    updateStatusHook.func_dict['TERMINATE'] = False

    logMessage('Starting conversion...')
    globalStatus = 'Converting...'
    updateStatusHook(globalStatus)
#    global srcName, destName,table,updateStatusHook,job
    job = ConverterThread(srcName=srcName.get(),
                          destName=destName.get(),
                          pretty_html= prettyHtml.get(),
                          callbackFunc=updateStatusHook)
    job.start()

def stopConversion(event=None):
    global job
    if (job and job.isAlive()):
        if tkMessageBox.askokcancel("Abort Operation",
                                    "Conversion has not finished yet. Are you sure you want to abort?"):
            logMessage('Stopping import... Please wait while cleaning up...')
            updateStatusHook.func_dict['TERMINATE'] = True
            job = None

    else:
        logMessage('No job is running')


def rightClickHandler(event, menu):
    'shows a context menu on right-click'
    # create a menu
    # display the popup menu
##    try:
    menu.tk_popup(event.x_root, event.y_root, 0)
##    finally:
##        # make sure to release the grab (Tk 8.0a1 only)
##        popupMenu.grab_release()
##
#w.bind("<Button-3>", do_popup)



# Configure shortcuts
##root.bind("<Alt-KeyPress-n>", keyHandler)
root.bind("<Alt-KeyPress-x>", quitApp)
root.bind("<Alt-KeyPress-c>", doConversion)
root.bind("<Alt-KeyPress-o>", openFileName)
root.bind("<Control-KeyPress-o>", openFileName)

root.bind('<Alt-KeyPress-u>', lambda e:srcEntry.focus_set())
root.bind('<Alt-KeyPress-d>', lambda e:destEntry.focus_set())
root.bind('<Alt-KeyPress-s>', doConversion)
root.bind('<Alt-KeyPress-p>', stopConversion)

#root.bind('<KeyPress-Return>', doConversion )

root.bind("<Control-KeyPress-q>", quitApp)


menu = Menu(root)
root.config(menu=menu)
#root.title = "DSL Converter"

filemenu = Menu(menu, tearoff=0)
menu.add_cascade(label="File", menu=filemenu, underline=0)
##filemenu.add_command(label="New", command=newFile, underline=0)
filemenu.add_command(label="Open Source...", command=openFileName, underline=0)
filemenu.add_command(label="Select Target...", command=openDestFileName, underline=7)

##filemenu.add_command(label="Save...", command=saveFile, underline=0)
#filemenu.add_separator()
filemenu.add_command(label="Exit", command=destroyApp, underline=1)



editmenu = Menu(menu, tearoff=0)
menu.add_cascade(label="Edit", menu=editmenu, underline=0)
#editmenu.add_command(label='Set table name', command=setTitle, underline=4)
editmenu.add_command(label='Change color', command=setColor, underline=4)
editmenu.add_command(label='Clear log', command=lambda : log.delete(1.0, END), underline=0)
editmenu.add_command(label='Clear last line', command=lambda : log.delete("end -2 lines" , "end"), underline=1)


helpmenu = Menu(menu, tearoff=0)
menu.add_cascade(label="Help", menu=helpmenu, underline=0)
helpmenu.add_command(label="About...", command=helpAbout, underline=0)

#create a toolbar
toolbar = Frame(root, width=33)

##b = Button(toolbar, text="new", width=5, command=newFile, underline=0)
##b.pack(side=LEFT, padx=2, pady=2)
##
##b = Button(toolbar, text="Open", width=5, command=openFileName, underline=0)
##b.pack(side=LEFT, padx=2, pady=2)

#tableLabel = Label(toolbar, text='Database table: ')
#tableLabel.pack(side=LEFT)

#table = StringVar(toolbar,None)
#tableEntry = Entry (toolbar, textvariable=table, width=22)
#tableEntry.bind('<Enter>', lambda e : statusHint('Table name to create in the SQLite database') )
#tableEntry.bind('<Leave>', lambda e : statusRevert() )
#tableEntry.bind('<KeyPress-Return>', srcReturnHadler)
#tableEntry.pack(side=LEFT)
prettyHtml = BooleanVar(toolbar, True)
cbPrettyHtml = Checkbutton(toolbar, text="HTML header/footer", variable=prettyHtml)
cbPrettyHtml.bind('<Enter>', lambda e,hint='Include HTML header and footer in the output file' : statusHint(hint) )
cbPrettyHtml.bind('<Leave>', lambda e : statusRevert())

cbPrettyHtml.pack(side=LEFT)

convBtn = Button(toolbar,  text="Start", width=8, command=doConversion, underline=0)
convBtn.bind('<Enter>', lambda e,hint='Click to start conversion' : statusHint(hint) )
convBtn.bind('<Leave>', lambda e : statusRevert() )
convBtn.pack(side=LEFT, padx=22, pady=2)

stopBtn = Button(toolbar,  text="Stop", width=8, command=stopConversion, underline=3)
stopBtn.bind('<Enter>', lambda e,hint='Click to abort conversion' : statusHint(hint) )
stopBtn.bind('<Leave>', lambda e : statusRevert() )
stopBtn.pack(side=LEFT, padx=22, pady=2)


toolbar.pack(side=TOP)

#toolbar.pack(side=TOP, fill=X)


##frame = Frame(root, width=100, height=100,relief=RIDGE, borderwidth=1)
##frame.bind("<Button-1>", callback)
##frame.bind("<Double-Button-1>", callbackDbl)
##root.bind("<Key>", keyHandler)
##root.protocol("WM_DELETE_WINDOW", destroyApp)
####
####lclicker = Label(frame, text='clicker')
####lclicker.pack()
##frame.pack()

mid = Frame(root)

## SOURCE FRAME ################

srcFrame = Frame(mid, width=200, height=140)
srcLabel = Label(srcFrame, text="Source:", width=9, underline=2)
srcLabel.pack(side=LEFT, ipadx=1, padx=1)
srcName = StringVar(srcFrame, "Click button to select file...")


srcEntry = Entry(srcFrame,  bg='white', textvariable=srcName, width=75)
srcEntry.bind('<FocusIn>', lambda e : srcName.get().startswith('Click') and srcName.set(''))
srcEntry.bind('<Enter>', lambda e,hint='Path to source DSL file' : statusHint(hint) )
srcEntry.bind('<Leave>', lambda e : statusRevert() )

srcPopup = Menu(srcEntry, tearoff=0)
srcPopup.add_command(label="Open DSL Source", command=openFileName) # , command=next) etc...
srcPopup.add_separator()
srcPopup.add_command(label="Cancel", command=None) # , command=next) etc...

srcEntry.bind('<Button-3>', lambda e, menu=srcPopup : rightClickHandler(e, menu))

srcEntry.pack(side=LEFT, padx=5)
srcEntry.bind('<KeyPress-Return>', srcReturnHadler)

##srcPopup.add_command(label="Previous")
##srcPopup.add_separator()
##srcPopup.add_command(label="Home")


srcBtn = Button(srcFrame, text="...", width=2,pady=0, command=openFileName)
srcBtn.bind('<Enter>', lambda e : statusHint('Click to select file') )
srcBtn.bind('<Leave>', lambda e : statusRevert() )
srcBtn.pack(side=LEFT, padx=2, pady=2)

srcFrame.pack(side=TOP)


destFrame = Frame(mid,
           width=300,
           height=100,
           relief=FLAT,
           borderwidth=0)
destLabel =  Label(destFrame, text="Output file:", width=9, underline=7)
destLabel.pack(side=LEFT, padx=1)
destName = StringVar(None, None)
destEntry = Entry(destFrame,  bg='white', textvariable=destName, width=75)
destEntry.bind('<Enter>', lambda e,hint='Output HTML file' :  statusHint(hint) )
destEntry.bind('<Leave>', lambda e : statusRevert() )
destEntry.bind('<KeyPress-Return>', doConversion )
# TODO: write handler
destPopup = Menu(srcEntry, tearoff=0)
destPopup.add_command(label="Output HTML file", command=openFileName) # , command=next) etc...
destPopup.add_separator()
destPopup.add_command(label="Cancel", command=None) # , command=next) etc...

destEntry.bind('<Button-3>', lambda e, menu=destPopup : rightClickHandler(e, menu))

destEntry.pack(side=LEFT, padx=5 )

destBtn = Button(destFrame,
                 text="...",
                 width=2,
                 pady=0,
                 command=openDestFileName)
destBtn.bind('<Enter>',
             lambda e, hint='Click to select file' : statusHint(hint) )
destBtn.bind('<Leave>', lambda e : statusRevert() )

destBtn.pack(side=LEFT, padx=2, pady=2)

destFrame.pack(side=BOTTOM)

mid.pack(padx=10,pady=10)
# status bar
statusVar = StringVar(root,globalStatus)
status = Label(root,
               textvariable=statusVar,
               bd=1,
               relief=SUNKEN,
               anchor=W)
status.pack(side=BOTTOM, fill=X)

logVar = StringVar(root,globalStatus)

logFrame = Frame(root)

scrollbar = Scrollbar(logFrame)
scrollbar.pack(side=RIGHT, fill=Y)

log = Text(logFrame,
           relief=RIDGE,
           wrap=WORD,
           yscrollcommand=scrollbar.set,
#           background='#dcf8e6',
#           background='SystemButtonFace',

height=15)
#log.yview_pickplace('end')
#log.see('end')
scrollbar.config(command=log.yview)

logPopup = Menu(log, tearoff=0)
logPopup.add_command(label='Clear log', command=lambda : log.delete(1.0, END), underline=0)
log.bind('<Button-3>', lambda e, menu=logPopup : rightClickHandler(e, menu))
log.pack()
logFrame.pack()

root.mainloop()
